<template>
    <div>
        <el-form ref="formSpu" label-width="80px" size='small' :model="spu" :rules="rules">
            <el-form-item label="SPU名称" prop="spuName">
                <el-input v-model="spu.spuName" placeholder="请输入SPU名称"></el-input>
            </el-form-item>
            <el-form-item label="品牌" prop="tmId">
                <el-select  placeholder="请选择品牌" v-model="spu.tmId">
                    <el-option v-for="(tm) in trademarkList" :key="tm.id" :label="tm.tmName" :value="tm.id"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="SPU描述">
                <el-input type="textarea" rows="4" v-model="spu.description" placeholder="SPU描述"></el-input>
            </el-form-item>
            <el-form-item label="SPU图片">
                <!-- 上传图片：action图片上传地址  list-type:文件列表的类型 on-preview:图片预览的时候会触发 
                on-remove:当删除图片的时候会触发   file-list 上传的文件列表, 例如: [{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}] 
                -->
                <el-upload
                    action="/dev-api/admin/product/fileUpload"
                    list-type="picture-card"
                    :file-list="spuImages"
                    :on-success="handleAvatarSuccess"
                    :on-preview="handlePictureCardPreview"
                    :on-remove="handleRemove"
                    :before-upload="beforeAvatarUpload"
                    >
                    <i class="el-icon-plus"></i>
                </el-upload>
                <el-dialog :visible.sync="dialogVisible">
                    <img width="100%" :src="dialogImageUrl" alt="">
                </el-dialog>
            </el-form-item>
            <el-form-item label="销售属性">
                <el-select v-model="attrIdAndAttrName" :placeholder="`还有${unSelectSaleAttr.length}个未选中`">
                    <el-option v-for="(unselet) in unSelectSaleAttr" :key="unselet.id" :label="unselet.name" :value="`${unselet.id}:${unselet.name}`"></el-option>
                </el-select>
                <el-button type="primary"  icon="el-icon-plus" style="margin-left:10px" :disabled="!attrIdAndAttrName" @click="addSaleAttr">添加销售属性</el-button>
                 <!-- 销售属性表单-->
                <el-table border style="width: 100%" size="small" :data="spu.spuSaleAttrList">
                        <el-table-column type="index" label="序号" width="80px" align="center">
                        </el-table-column>
                        <el-table-column prop="saleAttrName" label="属性名" width="width">
                        </el-table-column>
                        <el-table-column prop="prop" label="属性值名称列表" width="width">
                            <!-- row拿到的是当前的spuSaleAttrList -->
                             <template v-slot:default="{row,$index}">
                                <el-tag v-for="(tag,index) in row.spuSaleAttrValueList" :key="tag.id" closable :disable-transitions="false" @close="handleClose(row,index)" size="small">{{tag.saleAttrValueName}}</el-tag>
                                <!-- 底下的结构为span与input切换 -->
                                <!--@keyup.enter.native="handleInputConfirm" --键盘回车事件   @blur="handleInputConfirm" --失去焦点事件-->
                                <el-input class="input-new-tag" v-if="row.inputVisible" v-model="row.inputValue" ref="saveTagInput" size="mini"
                                    @keyup.enter.native="handleInputConfirm(row)"
                                    @blur="handleInputConfirm(row)">
                                </el-input>
                                <el-button v-else class="button-new-tag" size="mini" @click="addSaleAttrValue(row,$index)">添加</el-button>
                             </template>
                        </el-table-column>
                        <el-table-column prop="prop" label="操作" width="width">
                            <template v-slot:default="{row,$index}">
                            <!-- 气泡确认框 -->
                            <el-popconfirm :title="`确定删除${row.saleAttrName}属性吗?`" @onConfirm="deleteTmpAttr($index)">  
                                <el-button slot="reference" type="danger" icon="el-icon-delete" size="mini">
                            </el-button></el-popconfirm>
                            </template>
                        </el-table-column>
                </el-table>
            </el-form-item>       
            <el-form-item style="margin-top: 18px;">
                <el-button type="primary" @click="addOrUpdateSpu">保存</el-button>
                <el-button @click="cancelSelect()">取消</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
export default {
    name:'SpuForm',
    data() {
      return {
        rules:{
            spuName:[{ required: true, message: '请输入SPU名称', trigger: 'blur' },],
            tmId:[{ required: true, message: '请选择品牌', trigger: 'change' }]
        },
        dialogImageUrl: '',
        dialogVisible: false,
        //存储SPU信息属性
        //spu属性初始化的时候是一个空对象，在修改SPU的时候，会向服务器发请求，返回SPU信息（对象），在修改时可以利用服务器返回的这个对象收集最新的数据提交给服务器
        //添加SPU时没有提前发送请求，需考虑数据收集存储问题。
        spu: {
            //三级分类的id
            "category3Id": '',
            //品牌id
            "tmId": '',
            //描述
            "description": "",
            //spu的名称
            "spuName": "",
            // 收集SPU图片信息
            "spuImageList": [
                {
                    "id": '',
                    "imgName": "",
                    "imgUrl": "",
                    "spuId": ''
                }
            ],
            // 平台属性与属性值收集
            "spuSaleAttrList": [
                {
                    "baseSaleAttrId": '',
                    "id": '',
                    "saleAttrName": "",
                    "spuId": '',
                    "spuSaleAttrValueList": [
                        {
                            "baseSaleAttrId": '',
                            "id": '',
                            "isChecked": "",
                            "saleAttrName": "",
                            "saleAttrValueName": "",
                            "spuId": ''
                        }
                    ]
                }
            ],
        },
        //input值存储
        inputValue: '',
        spuImages:[], //存放SPU图片
        trademarkList:[], //存储品牌的信息
        saleAttrList:[], //存放销售属性
        attrIdAndAttrName:'' //收集被选择的销售属性的id和name
       }
    },
    methods: {
        //点击添加spu按钮发送请求的函数
       async addSpuData(category3Id){
             //获取品牌信息
             let trademarkListResult = await this.$API.spu.reqTrademarkList()
            if (trademarkListResult.code == 200) {
                this.trademarkList = trademarkListResult.data
            }
            //获取平台全部销售属性
              let saleAttrListResult = await this.$API.spu.reqBaseSaleAttrList()
            if (saleAttrListResult.code == 200) {
                this.saleAttrList = saleAttrListResult.data     
            }
            //获取三级分类category3Id 
            this.spu.category3Id = category3Id
        },
        //添加或修改确认按钮 
        addOrUpdateSpu() {
            // 表单验证，整理数据，发送请求
            this.$refs.formSpu.validate(async (success) => {
            if(success){
              //1.整理照片墙的数据，name与url值需要赋值给imgName及imgUrl带给服务器
              this.spu.spuImageList = this.spuImages.map((item)=>{
                  return{
                    imgName:item.name,
                    imgUrl:(item.response&&item.response.data)||(item.url)
                  }
            })
            //发请求
            let result = await this.$API.spu.reqAddOrUpdateSpu(this.spu)
            if (result.code == 200) {
                this.$message(
                    {
                        message: (this.spu.id?"修改SPU成功":'添加SPU成功'),
                        type: 'success'
                    }
                )
                this.$emit('changeScene',{scene:0,flag:this.spu.id?'修改':'添加'})
            }
            //清除数据
            // Object.assign():es6中新增的方法可以合并对象
            // 组件实例this._data,操作data中的响应式数据
            // this.$options可以获取配置对象,配置对象的data函数执行，返回的响应式数据为初始值的
            Object.assign(this._data,this.$options.data())
                    }
            });
        },
        // 取消事件
        cancelSelect(){
            this.$emit('changeScene',{scene:0,flag:''})
            //取消后移除表单项的校验结果
            this.$refs.formSpu.clearValidate()
            //清除数据
            Object.assign(this._data,this.$options.data())
        },
        // 图片上传之前
        beforeAvatarUpload(file) {
            const isJPG = file.type === 'image/jpeg';
            const isPng = file.type === 'image/png';
            const isLt2M = file.size / 1024 / 1024 < 2;
            if (!isJPG && !isPng) {
                this.$message.error('上传头像图片只能是 JPG或PEG 格式!');
            }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!');
            }
            return (isJPG || isPng) && isLt2M;
        },
        // 上传图片相关回调
        handleAvatarSuccess(response, file, fileList) {
            //收集上传图片的信息
            this.spuImages = fileList
        },
        // 照片墙删除某个图片的时候触发
        handleRemove(file, fileList) {
            // file参数：代表的是删除的那张图片
            // fileList:照片墙删除某一张图片以后，剩余的其他的图片
            // console.log(file, fileList);
            // 收集照片墙图片的数据
            this.spuImageList = fileList
        },
        //照片墙图片预览的回调
        handlePictureCardPreview(file) {
            // file存储的图片的访问地址
            this.dialogImageUrl = file.url;
            // 对话框属性
            this.dialogVisible = true;
        },
        //删除属性值标签
        handleClose(row,index) {
            let vl =  row.spuSaleAttrValueList
            vl.splice(index,1);
        },
        // 添加属性值的回调
        addSaleAttrValue(row,index) {
            //点击销售属性值当中添加按钮的时候，需要由button变为input，通过当前销售属性的inputVisible控制
            this.$set(row,"inputVisible",true)
            this.$set(row,"inputValue",'')
            //把对input文本框的操作，推迟到下次DOM更新之后。否则页面上根本不存在input元素
            this.$nextTick(()=> {
                this.$refs.saveTagInput.$refs.input.focus();
            });
        },
        //input失去焦点|回车时的事件
        handleInputConfirm(row) {
            //解构出销售属性当中收集的数据
            const {baseSaleAttrId,inputValue} = row
            //添加spuSaleAttrValueList里添加新的对象，需要有baseSaleAttrId 和saleAttrValueName
            // 属性值为空，不做处理
            if (inputValue.trim()==''){
                // 切换成button
                row.inputVisible = false;
                return
            }
            //属性值不能重复
            let isRepat = row.spuSaleAttrValueList.some((item)=>{
               //如果item有属性值和当前添加的属性值相同
               return inputValue == item.saleAttrValueName
            }) 
            if(isRepat){
                //如果重复提示
                this.$message(
                    {
                        message: ("属性值重复，请重新输入"),
                        type: 'warning'
                    }
                )
                //并且使得input重新获取焦点
                this.$refs.saveTagInput.$refs.input.focus();
                return;
            }
            //不为空也没有重复正常往下走
            let newObj = {
                            baseSaleAttrId:baseSaleAttrId,
                            saleAttrValueName:inputValue
                        }
            //新增属性值
            row.spuSaleAttrValueList.push(newObj)
            row.inputVisible = false;
            row.inputValue = '';
        },
        //初始化SpuForm数据
        async initSpuData(spu) {
            // 获取SPU信息的数据
            let spuResult = await this.$API.spu.reqSpu(spu.id)
            if (spuResult.code == 200) {
                this.spu = spuResult.data
            }
            //获取品牌信息
            let trademarkListResult = await this.$API.spu.reqTrademarkList()
            if (trademarkListResult.code == 200) {
                this.trademarkList = trademarkListResult.data
            }
            //获取SPU图标
            let spuImageResult = await this.$API.spu.reqSpuImageList(spu.id)
            if (spuImageResult.code == 200) {
                let listArr = spuImageResult.data
                //由于照片墙显示图片的数据需要数组，数组里面的元素需要有name与url字段
                //需要把服务器返回的数据进行修改
                listArr.forEach(item => {
                    //遍历数组中的每一个对象，往对象中添加name与url属性
                     item.name = item.imgName
                     item.url = item.imgUrl
                });
                this.spuImages = listArr
            }
            //获取平台全部销售属性
            let saleAttrListResult = await this.$API.spu.reqBaseSaleAttrList()
            if (saleAttrListResult.code == 200) {
                this.saleAttrList = saleAttrListResult.data     
            }
        },
        //添加新的销售属性
        addSaleAttr() {
            //已经收集需要添加的销售属性的信息
            //把收集到的销售属性数据进行分割 --数组的解构赋值
            const [baseSaleAttrId, saleAttrName] = this.attrIdAndAttrName.split(":");
            //向SPU对象的spuSaleAttrList属性里面添加新的销售属性
            let newSaleAttr = {baseSaleAttrId, saleAttrName,spuSaleAttrValueList:[]}
            //添加新的销售属性
            this.spu.spuSaleAttrList.push(newSaleAttr);
            // 清空数据
            this.attrIdAndAttrName = '';
        },
        //删除销售属性
        deleteTmpAttr($index){
        this.spu.spuSaleAttrList.splice($index,1)
        }

    },
    computed:{
        // 计算出还未选择的销售属性
        unSelectSaleAttr(){
            //整个平台的销售属性一共三个：颜色、尺寸、版本
            //当前SPU拥有的属于自己的销售属性spu.spuSaleAttrList 
            // 数组的过滤方法，可以从已有的数组当中过滤出用户需要的元素，并返回一个新的数组
            let result =  this.saleAttrList.filter((item)=>{
                //every数组的方法，会返回布尔值
                return this.spu.spuSaleAttrList.every((item1)=>{
                        return item.name != item1.saleAttrName
                })
            })
            return result
        }
    },
    mounted() {
        this.$bus.$on('getSpuId',(data)=>{
            console.log(data);
        })
    },
    beforeDestroy(){
         this.$bus.$off('getSpuId')
    }

}
</script>

<style>
.el-tag+.el-tag {
    margin-left: 10px;
}

.button-new-tag {
    margin-left: 10px;
    height: 32px;
    line-height: 30px;
    padding-top: 0;
    padding-bottom: 0;
}

.input-new-tag {
    width: 90px;
    margin-left: 10px;
    vertical-align: bottom;
}
</style>